package com.wenx.v3system.modular.cloud.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.wenx.base.rest.BaseRestController;
import com.wenx.v3core.response.R;
import com.wenx.v3secure.annotation.RequiresPermissions;
import com.wenx.v3secure.enums.SystemPermission;
import com.wenx.v3system.modular.cloud.domain.dto.SysMenuDto;
import com.wenx.v3system.modular.cloud.domain.query.SysMenuQuery;
import com.wenx.v3system.modular.cloud.service.SysMenuRestService;
import com.wenx.v3system.modular.cloud.service.SysRoleMenuService;
import com.wenx.v3system.modular.cloud.service.SysUserPermissionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

import static com.wenx.v3secure.annotation.RequiresPermissions.Logical.OR;

/**
 * 系统菜单管理Controller
 * 提供菜单的CRUD操作和树形结构管理
 * 基于Enhanced RBAC权限模型
 * 
 * @author wenx
 * @since 1.0.0
 */
@Slf4j
@Tag(name = "菜单管理", description = "系统菜单管理相关接口")
@RestController
@RequestMapping("/api/v3/sys/menus")
public class SysMenuRestController extends BaseRestController<SysMenuDto, SysMenuQuery, SysMenuRestService> {

    @Autowired
    private SysRoleMenuService roleMenuService;
    
    @Autowired
    private SysUserPermissionService rbacPermissionService;

    protected SysMenuRestController(SysMenuRestService service) {
        super(service);
    }

    // ============= 基础CRUD操作 =============

    /**
     * 分页查询菜单列表
     */
    @GetMapping
    @Operation(summary = "分页查询菜单", description = "根据查询条件分页获取菜单列表")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_READ_CODE}, logical = OR)
    public R getMenus(SysMenuQuery query) {
        IPage<?> pageResult = service.page(query);
        return R.ok(pageResult);
    }

    /**
     * 获取所有菜单（不分页）
     */
    @GetMapping("/all")
    @Operation(summary = "获取所有菜单", description = "获取所有菜单列表，不分页")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_READ_CODE}, logical = OR)
    public R getAllMenus() {
        // 使用树形结构获取所有菜单
        List<SysMenuDto> menus = service.getMenuTree(null);
        return R.ok(menus);
    }

    /**
     * 获取菜单树
     */
    @GetMapping("/tree")
    @Operation(summary = "获取菜单树", description = "获取菜单树形结构")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_READ_CODE}, logical = OR)
    public R getMenuTree(
            @Parameter(description = "菜单类型") @RequestParam(required = false) Integer type,
            @Parameter(description = "状态") @RequestParam(required = false) Integer status) {
        List<SysMenuDto> tree = service.getMenuTree(null);
        return R.ok(tree);
    }

    /**
     * 根据ID获取菜单详情
     */
    @GetMapping("/{id}")
    @Operation(summary = "获取菜单详情", description = "根据菜单ID获取菜单详细信息")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_READ_CODE}, logical = OR)
    public R getMenu(@PathVariable String id) {
        return R.ok(service.get(id));
    }

    /**
     * 创建菜单
     */
    @PostMapping
    @Operation(summary = "创建菜单", description = "创建新的菜单")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_ALL_CODE}, logical = OR)
    public R createMenu(@RequestBody @Valid SysMenuDto dto) {
        service.add(dto);
        // 清除相关权限缓存
        rbacPermissionService.clearAllPermissionCache();
        return R.ok();
    }

    /**
     * 更新菜单
     */
    @PutMapping("/{id}")
    @Operation(summary = "更新菜单", description = "更新菜单信息")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_ALL_CODE}, logical = OR)
    public R updateMenu(@PathVariable String id, @RequestBody @Valid SysMenuDto dto) {
        log.info("更新菜单: menuId={}", id);
        
        service.update(dto);
        // 清除所有权限缓存（因为菜单更新可能影响权限）
        rbacPermissionService.clearAllPermissionCache();
        
        return R.ok();
    }

    /**
     * 删除菜单
     */
    @DeleteMapping("/{id}")
    @Operation(summary = "删除菜单", description = "删除菜单并清理相关权限缓存")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_ALL_CODE}, logical = OR)
    public R deleteMenu(@PathVariable String id) {
        log.info("删除菜单: menuId={}", id);
        
        // 检查是否有子菜单
        List<SysMenuDto> children = service.getChildMenus(Long.valueOf(id));
        if (!children.isEmpty()) {
            return R.failed(null, "该菜单下还有子菜单，无法删除");
        }
        
        service.delete(id);
        // 清除所有权限缓存（因为菜单删除影响所有相关用户）
        rbacPermissionService.clearAllPermissionCache();
        
        return R.ok();
    }

    // ============= 扩展功能接口 =============

    /**
     * 批量删除菜单
     */
    @DeleteMapping("/batch")
    @Operation(summary = "批量删除菜单", description = "批量删除多个菜单")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_ALL_CODE}, logical = OR)
    public R batchDeleteMenus(@RequestBody List<String> ids) {
        log.info("批量删除菜单: menuIds={}", ids);
        
        for (String id : ids) {
            // 检查是否有子菜单
            List<SysMenuDto> children = service.getChildMenus(Long.valueOf(id));
            if (!children.isEmpty()) {
                return R.failed(null, "菜单ID " + id + " 下还有子菜单，无法删除");
            }
        }
        
        // 批量删除
        for (String id : ids) {
            service.delete(id);
        }
        
        rbacPermissionService.clearAllPermissionCache();
        return R.ok();
    }

    /**
     * 根据菜单编码获取菜单
     */
    @GetMapping("/code/{code}")
    @Operation(summary = "根据编码获取菜单", description = "根据菜单编码获取菜单信息")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_READ_CODE}, logical = OR)
    public R getMenuByCode(@PathVariable String code) {
        log.debug("根据编码获取菜单: code={}", code);
        
        SysMenuDto menu = service.getMenuByCode(code);
        if (menu == null) {
            return R.failed(null, "菜单不存在，编码: " + code);
        }
        
        return R.ok(menu);
    }

    /**
     * 获取用户菜单树
     */
    @GetMapping("/user/{userId}")
    @Operation(summary = "获取用户菜单", description = "获取指定用户的菜单权限树")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_READ_CODE}, logical = OR)
    public R getUserMenus(@PathVariable Long userId) {
        log.debug("获取用户菜单: userId={}", userId);
        
        List<SysMenuDto> userMenus = service.getUserMenus(userId);
        return R.ok(userMenus);
    }

    /**
     * 获取角色菜单
     */
    @GetMapping("/role/{roleId}")
    @Operation(summary = "获取角色菜单", description = "获取指定角色的菜单权限")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_READ_CODE}, logical = OR)
    public R getRoleMenus(@PathVariable Long roleId) {
        log.debug("获取角色菜单: roleId={}", roleId);
        
        List<SysMenuDto> roleMenus = service.getRoleMenus(roleId);
        return R.ok(roleMenus);
    }

    /**
     * 获取子菜单列表
     */
    @GetMapping("/{parentId}/children")
    @Operation(summary = "获取子菜单", description = "获取指定菜单的子菜单列表")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_READ_CODE}, logical = OR)
    public R getChildMenus(@PathVariable Long parentId) {
        log.debug("获取子菜单: parentId={}", parentId);
        
        List<SysMenuDto> children = service.getChildMenus(parentId);
        return R.ok(children);
    }

    /**
     * 获取菜单关联角色
     */
    @GetMapping("/{menuId}/roles")
    @Operation(summary = "获取菜单关联角色", description = "获取拥有该菜单权限的所有角色")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_READ_CODE}, logical = OR)
    public R getMenuRoles(@PathVariable Long menuId) {
        log.debug("获取菜单关联角色: menuId={}", menuId);
        
        List<Long> roleIds = roleMenuService.getRoleIdsByMenuId(menuId);
        return R.ok(roleIds);
    }

    // ============= 状态管理接口 =============

    /**
     * 启用菜单
     */
    @PutMapping("/{id}/enable")
    @Operation(summary = "启用菜单", description = "启用指定菜单")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_ALL_CODE}, logical = OR)
    public R enableMenu(@PathVariable String id) {
        log.info("启用菜单: menuId={}", id);
        
        service.enableMenu(Long.valueOf(id));
        rbacPermissionService.clearAllPermissionCache();
        
        return R.ok();
    }

    /**
     * 禁用菜单
     */
    @PutMapping("/{id}/disable")
    @Operation(summary = "禁用菜单", description = "禁用指定菜单")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_ALL_CODE}, logical = OR)
    public R disableMenu(@PathVariable String id) {
        log.info("禁用菜单: menuId={}", id);
        
        service.disableMenu(Long.valueOf(id));
        rbacPermissionService.clearAllPermissionCache();
        
        return R.ok();
    }

    // ============= 移动和排序接口 =============

    /**
     * 移动菜单
     */
    @PutMapping("/move")
    @Operation(summary = "移动菜单", description = "移动菜单到新的父级或调整排序")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_ALL_CODE}, logical = OR)
    public R moveMenu(@RequestBody @Valid Map<String, Object> request) {
        String menuId = (String) request.get("menuId");
        String targetParentId = (String) request.get("targetParentId");
        Integer targetSort = (Integer) request.get("targetSort");
        
        log.info("移动菜单: menuId={}, targetParentId={}, targetSort={}", menuId, targetParentId, targetSort);
        
        Long menuIdLong = Long.valueOf(menuId);
        Long targetParentIdLong = targetParentId != null ? Long.valueOf(targetParentId) : null;
        
        service.moveMenu(menuIdLong, targetParentIdLong, targetSort);
        rbacPermissionService.clearAllPermissionCache();
        
        return R.ok();
    }

    /**
     * 批量更新排序
     */
    @PutMapping("/batch-sort")
    @Operation(summary = "批量更新排序", description = "批量更新菜单排序")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_ALL_CODE}, logical = OR)
    public R batchUpdateSort(@RequestBody List<SysMenuDto> menuSorts) {
        log.info("批量更新菜单排序: 数量={}", menuSorts.size());
        
        service.updateMenuSorts(menuSorts);
        rbacPermissionService.clearAllPermissionCache();
        
        return R.ok();
    }

    // ============= 检查和验证接口 =============

    /**
     * 检查菜单编码是否存在
     */
    @GetMapping("/check-code")
    @Operation(summary = "检查菜单编码", description = "检查菜单编码是否已存在")
    @RequiresPermissions(value = {SystemPermission.SYSTEM_ALL_CODE, SystemPermission.MENU_READ_CODE}, logical = OR)
    public R checkMenuCode(
            @Parameter(description = "菜单编码") @RequestParam String code,
            @Parameter(description = "排除的菜单ID") @RequestParam(required = false) String excludeId) {
        
        Long excludeIdLong = excludeId != null ? Long.valueOf(excludeId) : null;
        boolean exists = service.existsByCode(code, excludeIdLong);
        
        return R.ok(Map.of("exists", exists));
    }
}
